<template>
  <nav-bar />
  <view class="version-page">
    <!-- 顶部导航 -->
    <view class="nav-bar">
      <text class="nav-back" @click="onBack">&#8592;</text>
      <text class="nav-title">版本列表</text>
    </view>

    <!-- 新版本提示 -->
    <view v-if="isLatest" class="latest-tip">
      <text class="tip-icon">✔</text>
      <text class="tip-text">已是最新版本</text>
    </view>
    <view v-else class="latest-tip latest-tip-warning">
      <text class="tip-icon">&#9888;</text>
      <text class="tip-text">有新版本可用</text>
    </view>

    <!-- 版本列表 -->
    <view class="version-list">
      <view class="version-card" v-for="(item, idx) in versionList" :key="item.version_id" @click="openDetail(item)">
        <view class="card-header">
          <text class="version-number">v{{ item.version_number }}</text>
          <text class="status-badge" :class="statusClass(item.version_status)">{{ item.version_status }}</text>
        </view>
        <view class="card-desc">{{ limitDesc(item.version_description) }}</view>
        <view class="card-footer">
          <text class="footer-label">发布时间：</text>
          <text class="footer-value">{{ item.create_time }}</text>
        </view>
        <view v-if="compareVersion(item.version_number, currentVersion) > 0 && item.version_status === '正常'" class="update-btn-bar">
          <button class="update-btn" @click.stop="updateToVersion(item)">更新到此版本</button>
        </view>
      </view>
    </view>

    <!-- 详情弹窗 -->
    <uni-popup ref="detailPopup" type="center">
      <view class="detail-popup">
        <view class="popup-header">
          <text class="popup-title">版本详情</text>
          <text class="popup-close" @click="closeDetailPopup">×</text>
        </view>
        <view class="popup-content">
          <view class="detail-row">
            <text class="detail-label">版本号：</text>
            <text class="detail-value">v{{ detail.version_number }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">描述：</text>
            <text class="detail-value">{{ detail.version_description }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">状态：</text>
            <text class="status-badge" :class="statusClass(detail.version_status)">{{ detail.version_status }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">发布者：</text>
            <text class="detail-value">{{ detail.version_publisher }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">发布时间：</text>
            <text class="detail-value">{{ detail.create_time }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">更新时间：</text>
            <text class="detail-value">{{ detail.update_time }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">分类：</text>
            <scroll-view class="type-list" scroll-y>
              <template v-if="detail.version_type && detail.version_type.length">
                <view v-for="(type, i) in detail.version_type" :key="i" class="type-item">
                  <text class="type-badge" :class="typeClass(type.version_update_type)">{{ type.version_update_type }}</text>
                  <text class="type-desc">{{ type.version_update_description }}</text>
                </view>
              </template>
              <template v-else>
                <text class="type-badge type-default">暂无分类</text>
              </template>
            </scroll-view>
          </view>
          <view class="detail-row">
            <text class="detail-label">图片：</text>
            <scroll-view class="image-scroll" scroll-x>
              <template v-if="detail.version_image && detail.version_image.length">
                <image v-for="(img, i) in detail.version_image" :key="i" :src="IntranetConfig.domain + img.image" class="detail-img-thumb" mode="aspectFill" @click="previewImg(i)" />
              </template>
              <template v-else>
                <text class="no-image-tip">暂无图片</text>
              </template>
            </scroll-view>
          </view>
        </view>
      </view>
    </uni-popup>

    <toast
      v-model="showToast"
      :content="toastContent"
      :type="toastType"
      :duration="toastDuration"
    />

    <message-box
      v-model="showMsgBox"
      :title="msgBoxTitle"
      :content="msgBoxContent"
      :showCancel="msgBoxShowCancel"
      :confirmText="msgBoxConfirmText"
      :cancelText="msgBoxCancelText"
      @confirm="onMsgBoxConfirm"
      @cancel="onMsgBoxCancel"
    />

    <!-- 下载进度弹窗 -->
    <uni-popup ref="downloadPopup" type="center">
      <view class="download-popup">
        <view class="popup-header">
          <text class="popup-title">下载进度</text>
          <text class="popup-close" @click="cancelDownload">×</text>
        </view>
        <view class="popup-content">
          <view class="progress-info">
            <view class="progress-bar">
              <view class="progress-inner" :style="{ width: downloadProgress + '%' }"></view>
            </view>
            <view class="progress-text">
              <text class="progress-percent">{{ downloadProgress }}%</text>
              <text class="progress-size">{{ formatSize(downloadedSize) }} / {{ formatSize(totalSize) }}</text>
            </view>
          </view>
          <view class="download-status">{{ downloadStatus }}</view>
        </view>
      </view>
    </uni-popup>
  </view>
</template>
  
<script setup>
import { ref, onMounted, computed } from 'vue'
import { IntranetConfig } from '@/static/js/config'
import Toast from '@/components/toast/toast.vue'
import MessageBox from '@/components/message-box/message-box.vue'

const versionList = ref([])
const detail = ref({})
const isLatest = ref(true)
const currentVersion = ref('') // 当前APP版本号
const detailPopup = ref(null)
const imgPreviewList = ref([])
const imgPreviewIndex = ref(0)
const showToast = ref(false)
const toastContent = ref('')
const toastType = ref('')
const toastDuration = ref(2000)
const showMsgBox = ref(false)
const msgBoxTitle = ref('')
const msgBoxContent = ref('')
const msgBoxShowCancel = ref(true)
const msgBoxConfirmText = ref('确定')
const msgBoxCancelText = ref('取消')
let msgBoxCallback = null
const downloadPopup = ref(null)
const downloadProgress = ref(0)
const downloadedSize = ref(0)
const totalSize = ref(0)
const downloadStatus = ref('准备下载...')
let downloadTask = null

// 比较两个版本号字符串，返回1:a>b，-1:a<b，0:相等
function compareVersion(a, b) {
  const arrA = a.split('.').map(Number)
  const arrB = b.split('.').map(Number)
  const len = Math.max(arrA.length, arrB.length)
  for (let i = 0; i < len; i++) {
    const nA = arrA[i] || 0
    const nB = arrB[i] || 0
    if (nA > nB) return 1
    if (nA < nB) return -1
  }
  return 0
}

// 获取当前APP版本号（manifest.json versionName）
function getCurrentAppVersion() {
  let v = ''
  // #ifdef APP-PLUS
  v = plus.runtime.version
  // #endif
  // #ifdef H5
  if (typeof __uniConfig !== 'undefined' && __uniConfig && __uniConfig.appVersion) {
    v = __uniConfig.appVersion
  } else if (window.__UNI__VERSION__) {
    v = window.__UNI__VERSION__
  }
  // #endif
  console.log('当前APP版本号:', v)
  return v
}

// 状态色
function statusClass(status) {
  if (status === '正常') return 'status-success'
  if (status === '维护') return 'status-warning'
  return 'status-default'
}
// 分类色
function typeClass(type) {
  if (type === '新增') return 'type-success'
  if (type === '优化') return 'type-primary'
  if (type === '修复') return 'type-warning'
  if (type === '删除') return 'type-danger'
  return 'type-default'
}

// 限制描述长度
function limitDesc(desc) {
  if (!desc) return ''
  return desc.length > 40 ? desc.slice(0, 40) + '...' : desc
}

// 获取版本列表
async function getVersionList() {
  uni.showLoading({ title: '加载中...' })
  try {
    const res = await uni.request({
      url: IntranetConfig.domain + 'api/version/get_version_list/',
      method: 'GET',
      header: IntranetConfig.headers
    })
    if (res.data.code === 200) {
      versionList.value = res.data.data
      // 找到最大版本号
      let maxVersion = ''
      versionList.value.forEach(v => {
        if (!maxVersion || compareVersion(v.version_number, maxVersion) > 0) {
          maxVersion = v.version_number
        }
      })
      // 获取当前APP版本
      currentVersion.value = getCurrentAppVersion()
      console.log(currentVersion.value, maxVersion)
      
      // 判断是否最新
      isLatest.value = compareVersion(currentVersion.value, maxVersion) >= 0
    }
  } catch (e) {
    uni.showToast({ title: '获取版本失败', icon: 'none' })
  } finally {
    uni.hideLoading()
  }
}

async function openDetail(item) {
  // 重新请求单个版本详情，确保有version_type和version_image
  try {
    const res = await uni.request({
      url: IntranetConfig.domain + 'api/version/get_version/' + item.version_id + '/',
      method: 'GET',
      header: IntranetConfig.headers
    })
    if (res.data.code === 200) {
      detail.value = res.data.data
      imgPreviewList.value = (detail.value.version_image || []).map(img => img.image)
      imgPreviewIndex.value = 0
      detailPopup.value.open()
    } else {
      uni.showToast({ title: '获取详情失败', icon: 'none' })
    }
  } catch (e) {
    uni.showToast({ title: '获取详情失败', icon: 'none' })
  }
}

function closeDetailPopup() {
  detailPopup.value.close()
}
function previewImg(idx) {
  // 预览所有图片，支持切换
  const urls = (detail.value.version_image || []).map(img => IntranetConfig.domain + img.image)
  uni.previewImage({
    urls,
    current: idx
  })
}
function onBack() {
  uni.navigateBack()
}

function showCustomToast(content, type = '', duration = 2000) {
  toastContent.value = content
  toastType.value = type
  toastDuration.value = duration
  showToast.value = true
}

function openMsgBox({ title = '', content = '', showCancel = true, confirmText = '确定', cancelText = '取消', callback = null }) {
  msgBoxTitle.value = title
  msgBoxContent.value = content
  msgBoxShowCancel.value = showCancel
  msgBoxConfirmText.value = confirmText
  msgBoxCancelText.value = cancelText
  msgBoxCallback = callback
  showMsgBox.value = true
}

function onMsgBoxConfirm() {
  if (msgBoxCallback) msgBoxCallback(true)
}

function onMsgBoxCancel() {
  if (msgBoxCallback) msgBoxCallback(false)
}

// 格式化文件大小
function formatSize(bytes) {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 取消下载
function cancelDownload() {
  if (downloadTask) {
    downloadTask.abort()
    downloadTask = null
  }
  downloadPopup.value.close()
  downloadProgress.value = 0
  downloadedSize.value = 0
  totalSize.value = 0
  downloadStatus.value = '准备下载...'
}

// 更新下载进度
function updateDownloadProgress(downloaded, total) {
  downloadedSize.value = downloaded
  totalSize.value = total
  downloadProgress.value = Math.floor((downloaded / total) * 100)
}

function updateToVersion(item) {
  if (item.version_status !== '正常') {
    showCustomToast('该版本不可下载', 'error')
    return
  }
  // #ifdef APP-PLUS
  if (item.version_download_url) {
    openMsgBox({
      title: '升级提示',
      content: `是否下载并安装版本 ${item.version_number}？`,
      showCancel: true,
      confirmText: '确认',
      cancelText: '取消',
      callback: (confirm) => {
        if (confirm) {
          downloadPopup.value.open()
          downloadStatus.value = '正在获取文件信息...'
          
          // 先获取文件大小
          plus.net.XMLHttpRequest.prototype.responseType = 'blob'
          const xhr = new plus.net.XMLHttpRequest()
          xhr.open('HEAD', item.version_download_url)
          xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                const contentLength = xhr.getResponseHeader('Content-Length')
                if (contentLength) {
                  totalSize.value = parseInt(contentLength)
                  startDownload(item.version_download_url)
                } else {
                  downloadStatus.value = '无法获取文件大小'
                  setTimeout(() => {
                    downloadPopup.value.close()
                  }, 1500)
                }
              } else {
                downloadStatus.value = '获取文件信息失败'
                setTimeout(() => {
                  downloadPopup.value.close()
                }, 1500)
              }
            }
          }
          xhr.send()
        }
      }
    })
  } else {
    showCustomToast('暂无下载地址', 'error')
  }
  // #endif
  // #ifdef H5
  if (item.version_download_url) {
    window.open(item.version_download_url, '_blank')
  } else {
    showCustomToast('暂无下载地址', 'error')
  }
  // #endif
}

// 开始下载
function startDownload(url) {
  downloadStatus.value = '正在下载...'
  
  downloadTask = plus.downloader.createDownload(url, {
    filename: '_downloads/',
    method: 'GET'
  }, function(d, status) {
    if (status === 200) {
      downloadStatus.value = '下载完成，准备安装...'
      downloadProgress.value = 100
      plus.runtime.install(d.filename, { force: true }, function() {
        downloadPopup.value.close()
        showCustomToast('安装成功', 'success')
      }, function(e) {
        downloadStatus.value = '安装失败'
        setTimeout(() => {
          downloadPopup.value.close()
        }, 1500)
        showCustomToast('安装失败', 'error')
      })
    } else {
      downloadStatus.value = '下载失败'
      setTimeout(() => {
        downloadPopup.value.close()
      }, 1500)
      showCustomToast('下载失败', 'error')
    }
  })
  
  // 监听下载状态变化
  downloadTask.addEventListener('statechanged', function(task, status) {
    switch (task.state) {
      case 1: // 开始
        downloadStatus.value = '正在下载...'
        break
      case 2: // 已连接到服务器
        downloadStatus.value = '已连接到服务器'
        break
      case 3: // 已接收到数据
        downloadedSize.value = task.downloadedSize
        // 直接更新进度，不使用 requestAnimationFrame
        downloadProgress.value = Math.floor((task.downloadedSize / totalSize.value) * 100)
        break
      case 4: // 下载完成
        downloadStatus.value = '下载完成，准备安装...'
        downloadProgress.value = 100
        break
      case 5: // 下载失败
        downloadStatus.value = '下载失败'
        setTimeout(() => {
          downloadPopup.value.close()
        }, 1500)
        break
    }
  })
  
  downloadTask.start()
}

onMounted(() => {
  getVersionList()
})
</script>
  
<style scoped lang="scss">
.version-page {
  background: #f8f9fa;
  min-height: 100vh;
  padding-bottom: 120rpx;
  font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
  overflow-x: hidden;
  max-width: 100vw;
  box-sizing: border-box;
}
.nav-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 32rpx;
  height: 96rpx;
  background: #fff;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  position: sticky;
  top: 0;
  z-index: 100;
  .nav-back {
    color: #333;
    font-size: 44rpx;
    width: 80rpx;
    height: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: all 0.3s;
    &:active { background: rgba(0, 0, 0, 0.05); }
  }
  .nav-title {
    flex: 1;
    text-align: center;
    font-size: 36rpx;
    font-weight: 600;
    color: #333;
  }
}
.latest-tip {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #e6f7e6;
  color: #52c41a;
  font-size: 28rpx;
  padding: 16rpx 0;
  .tip-icon { font-size: 32rpx; margin-right: 8rpx; }
  &.latest-tip-warning {
    background: #fffbe6;
    color: #faad14;
  }
}
.version-list {
  margin: 24rpx 32rpx;
  display: flex;
  flex-direction: column;
  gap: 24rpx;
}
.version-card {
  background: #fff;
  border-radius: 24rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
  padding: 32rpx;
  transition: box-shadow 0.2s;
  cursor: pointer;
  &:active { box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08); }
  .card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12rpx;
    .version-number { font-size: 32rpx; font-weight: 600; color: #333; }
    .status-badge {
      font-size: 26rpx;
      padding: 6rpx 18rpx;
      border-radius: 16rpx;
      font-weight: 500;
      &.status-success { background: #e6f7e6; color: #52c41a; }
      &.status-warning { background: #fffbe6; color: #faad14; }
      &.status-default { background: #f0f0f0; color: #999; }
    }
  }
  .card-desc {
    color: #666;
    font-size: 28rpx;
    margin-bottom: 16rpx;
    min-height: 40rpx;
    word-break: break-all;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .card-footer {
    color: #999;
    font-size: 24rpx;
    display: flex;
    align-items: center;
    .footer-label { margin-right: 8rpx; }
  }
}
.detail-popup {
  width: 650rpx;
  background: #fff;
  border-radius: 24rpx;
  overflow: hidden;
  box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
  .popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 32rpx;
    border-bottom: 1rpx solid #f5f5f5;
    background: #fff;
    .popup-title { font-size: 32rpx; font-weight: 600; color: #333; }
    .popup-close { font-size: 40rpx; color: #999; padding: 16rpx; margin: -16rpx; border-radius: 50%; transition: all 0.3s; &:active { background: #f5f5f5; } }
  }
  .popup-content {
    padding: 32rpx;
    background: #fff;
    .detail-row {
      display: flex;
      align-items: flex-start;
      margin-bottom: 18rpx;
      .detail-label { color: #666; width: 120rpx; flex-shrink: 0; font-size: 28rpx; }
      .detail-value { color: #333; font-size: 28rpx; word-break: break-all; }
      .status-badge {
        font-size: 26rpx;
        padding: 6rpx 18rpx;
        border-radius: 16rpx;
        font-weight: 500;
        &.status-success { background: #e6f7e6; color: #52c41a; }
        &.status-warning { background: #fffbe6; color: #faad14; }
        &.status-default { background: #f0f0f0; color: #999; }
      }
      .type-list {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 16rpx;
        max-height: 300rpx;
        overflow-y: auto;
        padding-right: 8rpx;
        &::-webkit-scrollbar {
          width: 6rpx;
        }
        &::-webkit-scrollbar-thumb {
          background-color: #ddd;
          border-radius: 3rpx;
        }
        &::-webkit-scrollbar-track {
          background-color: #f5f5f5;
          border-radius: 3rpx;
        }
        .type-item {
          display: flex;
          align-items: flex-start;
          gap: 16rpx;
          .type-badge {
            font-size: 24rpx;
            padding: 4rpx 16rpx;
            border-radius: 14rpx;
            font-weight: 500;
            background: #f0f0f0;
            color: #999;
            flex-shrink: 0;
            &.type-success { background: #e6f7e6; color: #52c41a; }
            &.type-primary { background: #e6f4ff; color: #1677ff; }
            &.type-warning { background: #fffbe6; color: #faad14; }
            &.type-danger { background: #fff1f0; color: #ff4d4f; }
            &.type-default { background: #f0f0f0; color: #999; }
          }
          .type-desc {
            font-size: 28rpx;
            color: #333;
            line-height: 1.5;
            flex: 1;
          }
        }
      }
    }
    .image-scroll {
      width: 100%;
      white-space: nowrap;
      margin-top: 8rpx;
      .detail-img-thumb {
        width: 120rpx;
        height: 120rpx;
        border-radius: 12rpx;
        object-fit: cover;
        margin-right: 16rpx;
        border: 1rpx solid #eee;
        display: inline-block;
      }
    }
  }
}
.type-badge-list .type-default {
  background: #f0f0f0;
  color: #999;
}
.no-image-tip {
  color: #bbb;
  font-size: 26rpx;
  padding: 0 12rpx;
  line-height: 120rpx;
}
.update-btn-bar {
  margin-top: 18rpx;
  display: flex;
  justify-content: flex-end;
}
.update-btn {
  background: #ff7e2d;
  color: #fff;
  border: none;
  border-radius: 12rpx;
  font-size: 28rpx;
  padding: 12rpx 36rpx;
  font-weight: 500;
  box-shadow: 0 2rpx 8rpx rgba(255,126,45,0.08);
  transition: all 0.2s;
}
.update-btn:active {
  background: #e36c1c;
}
.download-popup {
  width: 600rpx;
  background: #fff;
  border-radius: 24rpx;
  overflow: hidden;
  box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
  
  .popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 32rpx;
    border-bottom: 1rpx solid #f5f5f5;
    background: #fff;
    
    .popup-title {
      font-size: 32rpx;
      font-weight: 600;
      color: #333;
    }
    
    .popup-close {
      font-size: 40rpx;
      color: #999;
      padding: 16rpx;
      margin: -16rpx;
      border-radius: 50%;
      transition: all 0.3s;
      &:active {
        background: #f5f5f5;
      }
    }
  }
  
  .popup-content {
    padding: 32rpx;
    background: #fff;
    
    .progress-info {
      margin-bottom: 24rpx;
      
      .progress-bar {
        height: 8rpx;
        background: #f5f5f5;
        border-radius: 4rpx;
        overflow: hidden;
        margin-bottom: 16rpx;
        
        .progress-inner {
          height: 100%;
          background: #ff7e2d;
          border-radius: 4rpx;
          will-change: width;
        }
      }
      
      .progress-text {
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-size: 24rpx;
        color: #666;
        
        .progress-percent {
          font-weight: 500;
          color: #333;
        }
        
        .progress-size {
          color: #999;
        }
      }
    }
    
    .download-status {
      text-align: center;
      font-size: 28rpx;
      color: #666;
      margin-top: 16rpx;
    }
  }
}
</style>    
